"""The module for editing groups of elements on the side"""

from PyQt4 import QtGui, QtCore
from itertools import count
from types import GeneratorType

class EditWidget(QtGui.QWidget):
    """The side widget for editing a set of elements"""
    sClicked=QtCore.pyqtSignal()
    def __init__(self, atts, tableDisplay, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.__loadAtts(atts)
        self.__tableDisplay=tableDisplay
        self.__tableDisplay.sSelectedElements.connect(self.setElements)
        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
                                             QtGui.QSizePolicy.Maximum))
    def mousePressEvent(self, event):
        self.sClicked.emit()
    def __loadAtts(self, atts):
        """Loads a set of attributes for the widget"""
        layout=QtGui.QGridLayout(self)
        self.__lines=[]
        for att, row in zip(atts, count()):
            layout.addWidget(QtGui.QLabel(att, self), row, 0)
            layout.addWidget(QtGui.QLabel('=', self), row, 1)
            self.__lines.append(EditLine(att, self))
            layout.addWidget(self.__lines[-1], row, 2)
    def changeElements(self, att, value):
        """Changes all of the selected elements to the tableDisplay"""
        self.__tableDisplay.changeElements(att, value)
    @QtCore.pyqtSlot(GeneratorType)
    def setElements(self, elements):
        """Sets the edit as per the widgets selected"""
        elements=list(elements)
        for line in self.__lines:
            line.setElements(elements)

class EditLine(QtGui.QLineEdit):
    """The line edit which when changed changes the attributes of all selected
    elements"""
    def __init__(self, att, parent):
        QtGui.QLineEdit.__init__(self, parent)
        self.__att=att
        self.parent=parent
        self.textEdited.connect(self.__onTextEdit)
        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
                                             QtGui.QSizePolicy.Maximum))
    def __onTextEdit(self):
        self.parent.changeElements(self.__att, str(self.text()))
    def setElements(self, elements):
        """Sets the line to the common value if possible, otherwise to
        blank"""
        try:
            hashFn=lambda value: (tuple(value) if isinstance(value, list)
                             else value)
            if len(set(hashFn(element[self.__att]) for element in elements))==1:
                if isinstance(elements[0], list):
                    self.setText(str(elements[0][self.__att][0]))
                else:
                    self.setText(str(elements[0][self.__att]))
            else:
                self.setText('')
        except KeyError:
            self.setText('')
class ExpandingEditWidget(QtGui.QWidget):
    def __init__(self, atts, tableDisplay, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.__layout=QtGui.QVBoxLayout(self)
        self.__editWidget=EditWidget(atts, tableDisplay, self)
        collapseFunction=lambda : self.setEditActive(False)
        self.__editWidget.sClicked.connect(collapseFunction)
        self.__collapsedLine=_CollapsedLine(self)
        self.__layout.addWidget(self.__collapsedLine)
        self.__layout.addWidget(self.__editWidget)
        self.__editWidget.hide()
    def setEditActive(self, activatep):
        """Hides and shows the edit depending on activep. Not safe to use
        if not sure whether the edit is currently shown"""
        if activatep:
            self.__editWidget.show()
        else:
            self.__editWidget.hide()
            

class _CollapsedLine(QtGui.QLabel):
    def __init__(self, parent):
        QtGui.QLabel.__init__(self, 'Edit', parent)
        self.setAlignment(QtCore.Qt.AlignHCenter)
        self.setSizePolicy(QtGui.QSizePolicy.Minimum,
                           QtGui.QSizePolicy.Minimum)
        self.__parent=parent
        self.activatep=False
    def mousePressEvent(self, event):
        self.__parent.setEditActive(self.activatep)
        self.activatep=not self.activatep

